package org.third.integration.kubernates.batch.imp;

import java.io.InputStream;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import org.springframework.util.StringUtils;
import org.third.common.exception.BadRequestException;
import org.third.common.utils.StreamUtils;
import org.third.integration.kubernates.batch.KubeBatch;
import org.third.integration.kubernates.batch.bean.BatchInfo;
import org.third.integration.kubernates.batch.bean.KubeInstanceMetaDTO;
import org.third.integration.kubernates.batch.utils.K8sYamlUtils;
import org.third.integration.kubernates.cmd.imp.exp.RequestApiServerException;
import org.third.integration.kubernates.cmd.imp.utils.K8S_TYPE_UTILS;

import com.esotericsoftware.yamlbeans.YamlException;
import com.esotericsoftware.yamlbeans.YamlReader;

public class SuiteKubeBatchDecorator implements KubeBatch{
	
	private KubeBatch kubeBatch;
	private String namespace;
	private String labelKey;
	private String labelValue;
	
	public SuiteKubeBatchDecorator(KubeBatch kubeBatch,
			String namespace, String labelKey, String labelValue) {
		this.kubeBatch = kubeBatch;
		this.namespace = namespace;
		this.labelKey = labelKey;
		this.labelValue = labelValue;
	}
	
	@Override
	public BatchInfo create(List<InputStream> inputSteamList)
			throws RequestApiServerException {
		
		List<String> yamlContentList = checkSuiteYaml(inputSteamList);
		
		List<InputStream> splitInputSteamList = new ArrayList<InputStream>();
		for(String content : yamlContentList){
			splitInputSteamList.add(StreamUtils.stringToInputStream(content));
		}
		
		return this.kubeBatch.create(splitInputSteamList);
	}

	@SuppressWarnings({ "rawtypes", "unchecked" })
	private List<String> checkSuiteYaml(List<InputStream> inputSteamList){

		List<String> yamlContentList = new ArrayList<String>();
		for(InputStream is : inputSteamList){
			try {
				yamlContentList.addAll(K8sYamlUtils.split(is));
			} catch (Exception e) {
				throw new RuntimeException("Failed to split yaml content.", e);
			}
		}

		for(String yamlContent : yamlContentList){
			YamlReader yamlReader = new YamlReader(new StringReader(yamlContent));
			Map map = null;
			try {
				map = (Map) yamlReader.read();
			} catch (YamlException e) {
				throw new BadRequestException("Failed to parse yaml, " + yamlContent, e);
			}
			String type = K8S_TYPE_UTILS.getType((String) map.get("kind"));
			String apiVersion = (String) map.get("apiVersion");
			String instanceName = (String) ((Map) map.get("metadata")).get("name");
			String namespace = (String) ((Map) map.get("metadata")).get("namespace");

			String k8sInstanceInfo = String.format("type: [%s], apiVersion: [%s], instanceName: [%s], namespace: [%s]", type, apiVersion, instanceName, namespace);

			//check namespace
			if(!K8S_TYPE_UTILS.getSpecificTypes().contains(type)){
				if(StringUtils.isEmpty(namespace)){
					throw new BadRequestException("namespace can't be empty for " + k8sInstanceInfo);
				}else if(!namespace.equalsIgnoreCase(this.namespace)){
					throw new BadRequestException("namespace must be [" + this.namespace + "] for " + k8sInstanceInfo);
				}
			}

			//check name,version,type not empty
			if(StringUtils.isEmpty(instanceName) || StringUtils.isEmpty(apiVersion) || StringUtils.isEmpty(type)){
				throw new BadRequestException("type or apiVersion or name can't be empty for " + k8sInstanceInfo);
			}

			//check nodeSelector
			/*
			 * The check for nodeSelector was removed as a fix for QCCR1E143849.
			 * This removal was confirmed by CDF architect (Tim & Ralf). The CDF users takes the responsibility for pod assignment.
			 */
		}
		return yamlContentList;
	}

	@Override
	public BatchInfo create(InputStream inputSteam)
			throws RequestApiServerException {
		
		List<InputStream> inputSteamList = new ArrayList<InputStream>();
		inputSteamList.add(inputSteam);
		
		return this.create(inputSteamList);
	}

	@Override
	public BatchInfo get(List<KubeInstanceMetaDTO> kubeInstanceMetaList)
			throws RequestApiServerException {
		return kubeBatch.get(kubeInstanceMetaList);
	}

	@Override
	public BatchInfo get(KubeInstanceMetaDTO kubeInstanceMetaDTO)
			throws RequestApiServerException {
		return kubeBatch.get(kubeInstanceMetaDTO);
	}

	@Override
	public BatchInfo delete(List<KubeInstanceMetaDTO> kubeInstanceMetaList)
			throws RequestApiServerException {
		return kubeBatch.delete(kubeInstanceMetaList);
	}

	@Override
	public BatchInfo delete(KubeInstanceMetaDTO kubeInstanceMetaDTO)
			throws RequestApiServerException {
		return kubeBatch.delete(kubeInstanceMetaDTO);
	}

	@Override
	public BatchInfo getPodsUnderService(KubeInstanceMetaDTO serviceMetaDTO)
			throws RequestApiServerException {
		return kubeBatch.getPodsUnderService(serviceMetaDTO);
	}

}
